package de.tudarmstadt.gdi1.project.analyse;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import de.tudarmstadt.gdi1.project.alphabet.Alphabet;
import de.tudarmstadt.gdi1.project.alphabet.Dictionary;
import de.tudarmstadt.gdi1.project.alphabet.Distribution;
import de.tudarmstadt.gdi1.project.analysis.vigenere.VigenereCryptanalysis;
import de.tudarmstadt.gdi1.project.Charset;
import de.tudarmstadt.gdi1.project.FactoryIM;



public class VigenerAnalysis implements VigenereCryptanalysis {

    public LinkedList<Integer> allDividers1(int a){     // alleTeiler gibt alle Teiler einer Zahl a aus;
    	int b = 1;
    	LinkedList<Integer> c = new LinkedList<Integer>(); // 10.2
    	if(a >= b){
    		
    	
    	if ((a/b) == int){
    		c.add(a/b);
    		b++;
    		allDividers1(a);
    	}
    	b++;
    	allDividers1(a);
    	}
    	return c;
    }
     
    // Euklid berechnet den gr��ten Teiler zweier Zahlen mit hilfe des euklidischen Algorithmuses, 10.2
    
    public int Euklid(int a, int b){
        if (a == 0){                         
        	return b;
        }
        while(b != 0){                       
         if (a > b){
        	a = a - b;               
        	}
            else
        	{
        		a = b - a;               
        		}
        }
        return a; }
    
    // gr��terTeiler berechnet den gr��ten Teiler von einer Liste von Zahlen, 10.2
    
    public int biggestTeiler(ArrayList<Integer> h){
    	int j = 0;
    	int k = 1;
    	int teiler = 0;
    	while(k < h.size()){
    	teiler = Euklid(h.get(j), h.get(k));
    	j = teiler;
    	k = k + 2;
    }
    	return teiler;
    	}
    
    // Distanz berechnet die Distanzen zwischen den Stellen an denen der String im Text vorkommt, 10.2
    // @ param f, b, p, k sind Hilfparameter f�r die Rechnung
    // @ return gibt die Distanz zur�ck
    
    public ArrayList<Integer> Distanz(int g, String l, String s){ // muss noch korriegiert werden passt nicht ganz zur Aufgabenstellung
    	int f = l.length();
    	int b = 0;
    	int p = 0;
    	int k = 0;
    	int v = 0;
    	ArrayList<Integer> Abstand = new ArrayList<Integer>();
    	ArrayList<Integer> Distanz = new ArrayList<Integer>();
    	while (v <= s.length()){
    		String w = s.substring(b, f);
    		if (s.equals(w)){
    			Abstand.add(b);
    			b = f++;
    			f = f + s.length();
    		}
    		b = f++;
    		f = f + s.length();
    	}
    	while (p < Abstand.size()){
    		k = (Abstand.get( p)+3) - Abstand.get(p + 1);
    		Distanz.add(k);
    	}
    	return Distanz;
     }
    
    //Schl�ssell�nge berechnet die m�glichen Schl�ssell�ngen, 10.3
    //@ param Chiffretext ist der Text der zu entschl�sseln ist
    //@ return gibt eine ArrayList mit allen m�glichen Schl�ssell�ngen zur�ck
    
    public LinkedList<Integer>keylength(String Chiffretext, String g){
    	return allDividers1(biggestTeiler(Distanz(3, g, Chiffretext)));
    }
    
    // knownCiphertextAttack gibt eine Liste aller m�glichen Schl�ssell�ngen zur�ck, 10.3
    
    public List<Integer> knownCiphertextAttack(String Chipertext, String g){
    	return keylength(Chipertext, g);
    }
    
    // 10.3
    
    public void getVigenereCryptanalysisInstance() {
		// muss ich noch implementieren weis noch nicht was die Funktion machen soll
	}
    
    // 10.4 kownPlaintextAttack ermittelt den Schl�ssel wobei Klartext und Geheimtext beide bekannt sind
    // @param plaintext ist der Klartext
    // @param chipertext ist der Geheimtext
    // @param alphabet ist das benutzte Alphabet
    // @return Key gibt den Schl�ssel zur�ck
    
    public String knownPlaintextAttack(String plaintext, String chipertext, Alphabet alphabet){
    	int t = 0;
    	LinkedList<String> Key = new LinkedList<String>();
    	while(t < plaintext.length()){
    		int Verschiebung = getIndex(plaintext.get(t)) - getIndex(chipertext.get(t));
    		if (Key.containts(Charset.class.getChar(Verschiebung))){
    			return Key;
    		}
    		Key = Key.set(Charset.class.getChar(Verschiebung));
    		t++;
    	}
    	return Key;
    }
    
    // 10.5 knownCiphertextAttack ermittelt den Schl�ssel
    // @param ciphertext ist der Geheimtext
    // @param distribution 
    // @param cribs sind Textteile die man im Klartext hat
    // @return gibt den Schl�ssel zur�ck		
    
    
    public String knownCiphertextAttack(String ciphertext, Distribution distribution, List<String> cribs){
        String g;
    	keylength(ciphertext, g);
    	int k = 0;
    	ArrayList<String> key = new ArrayList<String>();
    	while (k < c<c.size()-1>){
    		String d = chipertext.substring(k, k);
    	    key = key + key.get(ceasar.knownChipertextAttack(d, distribution)); 
    	}
    	return key;
    }
	@Override
	public Object knownPlaintextAttack(String ciphertext, String plaintext,
			Distribution distribution) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public Object knownPlaintextAttack(String ciphertext, String plaintext,
			Distribution distribution, Dictionary dictionary) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<Integer> knownCiphertextAttack(String ciphertext) {
		// TODO Auto-generated method stub
		return null;
	}
	
	


    
}
